/**
 * @author Omar Fouda
 * @version 1.0
 */

package controllers;

import play.mvc.Controller;
import models.ActionLog;
import models.EEntity;
import models.Notification;
import models.Organization;
import models.RoleInOrganization;
import models.User;
import models.RoleInEntity;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;

public class EEntities extends Controller {
	/**
	 * method used to edit an entity's name, description and lock
	 * status
	 * @param entId, id of entity to be edited
	 * @param entName, name of entity to be edited
	 * @param lock, lock status of entity to be edited
	 * @param entDescription, description of entity to be edited
	 * @author Omar Fouda
	 */
	public static void editEntity(String entId, String entName, String lock,
			String entDescription) {
//
//		validation.required(entName).message("Entity name is required");
//		validation.required(lock).message("lock status is required");
//		validation.required(entDescription).message(
//				"Entity description is required");

		int temp = Integer.parseInt(entId);
		long entityId2 = temp;

//		if (validation.hasErrors()) {
//			params.flash();
//			validation.keep();
//			editEntityView(entityId2);
//		}

		EEntity entity = EEntity.findById(entityId2);
		entity.name = entName;
		entity.description = entDescription;

		if (Integer.parseInt(lock) == 1) {
			entity.lockEntity();
		} else {
			entity.unlockEntity();
		}
		
		String actionLogMessage = null;
		String userName = session.get("username");
		User userForLog = User.find("userName", userName).first();
		if(userName!=null){
			actionLogMessage = "User name " + userName+ " edited an entity called " + entity.name;
			new ActionLog(actionLogMessage,userForLog,null).save();
		}	
		
		entity.save();

		if (entity != null) {
			Organizations.editOrg(entity.organization.id);
		}
	}

	/**
	 * method to remove an entity from a certain organizations
	 * 
	 * @author Omar Fouda
	 * @param entId
	 *            , id of the entity to be removed
	 * @param orgId
	 *            , id of the organization from which the entity should be
	 *            removed
	 */
	public static void removeEntity(long entId, long orgId) {
		EEntity toBeRemoved = EEntity.findById(entId);
		toBeRemoved.cascadeDelete();
		Organization org = toBeRemoved.organization;
		
		String actionLogMessage = null;
		String userName = session.get("username");
		User userForLog = User.find("userName", userName).first();
		if(userName!=null){
			actionLogMessage = "User name " + userName+ " removed an entity called " + toBeRemoved.name;
			new ActionLog(actionLogMessage,userForLog,null).save();
		}	
		
		renderTemplate("Browse/viewEntitiesOfOrg.html",org);
	}

	/**
	 * method to add an entity to a certain organization. It creates a new
	 * entity and assigns it to the organization then calls the view of editing
	 * the organization
	 * 
	 * @author Omar Fouda
	 * @param orgId
	 *            , organization of new entity
	 * @param entName
	 *            , name of new entity
	 * @param entDescrip
	 *            , description of new entity
	 * @param lock
	 *            , lock status of new entity
	 */
	public static void addEntityToOrg(String orgId, String entName,
			String entDescrip, String lock) {
		int temp1 = Integer.parseInt(orgId);
		long id = temp1;
		boolean locked;

		validation.required(orgId);
		validation.required(entName).message("Entity name is required");
		validation.required(entDescrip).message(
				"A brief entity description is required");
		validation.required(lock).message("Entity lock status is required");

		if (validation.hasErrors()) {
			params.flash();
			validation.keep();
			addEntity(id);
		}

		if (lock.equals("0"))
			locked = false;
		else
			locked = true;
		
		Organization org = Organization.findById(id);
		EEntity newEntity = new EEntity(entName, entDescrip, org, locked).save();
		org.entities.add(newEntity);
		
		String actionLogMessage = null;
		String userName = session.get("username");
		User userForLog = User.find("userName", userName).first();
		
		if(userName!=null){
			actionLogMessage = "User name " + userName+ " added an entity called " + entName;
			new ActionLog(actionLogMessage,userForLog,null).save();
		}
		
		
		LinkedList<User> toBeNotified = new LinkedList<User>();
		for (User user : org.followingUsers) {
			if (!toBeNotified.contains(user))
				toBeNotified.add(user);
		}
		User organizationLead = null;
		organizationLead = org.getOrganizationLead();
		Notification newNotification = new Notification("A new entity has been " +
				"added to organization " + org.name, newEntity.id, 3, organizationLead, toBeNotified);
		newNotification.timeStamp = new Date();
		newNotification.save();
		Organizations.editOrg(id);
	}
	
	/**
	 * method to render a template containg the form to add
	 * an entity to an organization
	 * @author omar fouda
	 * @param orgId, id of the organization to which
	 * the entity will be added
	 */

	public static void addEntity(long orgId) {
		renderTemplate("/EEntities/addEntity.html",orgId);
	}

	/**
	 * Method to render the edit entity view
	 * 
	 * @author Omar Fouda
	 * @param id
	 *            , id of the entity to be viewed
	 */

	public static void editEntityView(long id) {
		EEntity ent = EEntity.find("byId", id).first();

		renderTemplate("/EEntities/editEntityView.html",ent);
	}

	/**
	 * This method removes an entity member from the entity,it calls the
	 * removeMember method in the EEntity model with the user's id as a
	 * parameter. then renders a template of the members of the entity
	 * 
	 * @author Omar Fouda
	 * @param userId
	 *            , id of the user to be removed
	 * @param entityId
	 *            , id of the entity to remove him/her from
	 * @param isAllowedToPost
	 *            , true only if the user is the organization lead or the
	 *            organizor if this entity
	 * @param isSystemAdmin, incicates if hes the admin
	 * @param isOrganizationLead, indicates if he's the lead
	 */
	public static void removeMember(long userId, long entityId,
			boolean isAllowedToPost, boolean isSystemAdmin, boolean isOrganizationLead) {
		System.out.println("heeeeeeeeeeeeeeee");
		EEntity entity = EEntity.findById(entityId);
		entity.removeMember(userId);
		
		List<User> members = new ArrayList<User>();

		for (int i = 0; i < entity.rolesAndUsers.size(); i++) {
			members.add(entity.rolesAndUsers.get(i).user);
		}

		User toBeRemoved = User.findById(userId);
		String actionLogMessage = null;
		String userName = session.get("username");
		User userForLog = User.find("userName", userName).first();
		
		if(userName!=null){
				if(userName.equals(toBeRemoved.userName)){
					String gender = null;
					if(toBeRemoved.gender.equalsIgnoreCase("male")){
						gender = "himself";
					}
					else{
						gender = "herself";
					}
					actionLogMessage = "User name " + userName+ " removed " + gender +" from entity "  + entity.name;
				}
				else{		
			actionLogMessage = "User name " + userName+ " removed " + toBeRemoved.userName +" from entity "  + entity.name;
				}
			new ActionLog(actionLogMessage,userForLog,null).save();
		}
				
		
		renderTemplate("Browse/viewEntityMembers.html",members,entity,isAllowedToPost,isSystemAdmin,isOrganizationLead);
		//Browse.viewEntity(entityId);
	}

	/**
	 * Method to display all the members of a certain entity by checking that
	 * they have any role in this entity
	 * 
	 * @author Omar Fouda
	 * @param entityId
	 *            , the id of the entity to be viewed
	 * @param isAllowedToPost
	 *            , booelan variable that indicates if the user viewing the
	 *            members has the permission to remove a member.
	 */
	public static void viewMembers(long entityId, boolean isAllowedToPost) {
		EEntity entity = EEntity.findById(entityId);
		List<User> members = new ArrayList<User>();

		for (int i = 0; i < entity.rolesAndUsers.size(); i++) {
			members.add(entity.rolesAndUsers.get(i).user);
		}

		render(entity, members, isAllowedToPost);
	}

	/**
	 * @author Zeyad Gasser
	 * @component 1
	 * @userStory 14
	 * 
	 *            Blocks a user from an entity by adding him to a list of
	 *            blocked users
	 * 
	 * @param id
	 * @param entity
	 * @param isAllowedToPost
	 */

	public static void blockUser(long userId, long entityId,
			boolean isAllowedToPost) {
		User userById = User.findById(userId);
		EEntity entity = EEntity.getEntityById(entityId);
		entity.blockedFromEntity.add(userById);
		userById.blockedEntities.add(entity);
		entity.save();
		userById.save();
		String username = session.get("username");
		User user = User.getUserInfo(username);
		String msg = "User id " + userId + " was blocked";
		new ActionLog(msg, user, null).save();
		Browse.viewEntity(entity.id);
	}

	/**
	 * @author Zeyad Gasser
	 * @component 1
	 * @userStory 14
	 * 
	 *            Unblocks a user from an entity by removing him to a list of
	 *            blocked users
	 * 
	 * @param userid
	 * @param entity
	 * @param isAllowedToPost
	 */

	public static void unblockUser(long userId, long entityId,
			boolean isAllowedToPost) {
		User userById = User.findById(userId);
		EEntity entity = EEntity.getEntityById(entityId);
		entity.blockedFromEntity.remove(userById);
		userById.blockedEntities.remove(entity);
		entity.save();
		userById.save();
		String username = session.get("username");
		User user = User.getUserInfo(username);
		String msg = "User id " + userId + " was unblocked";
		new ActionLog(msg, user, null).save();
		Browse.viewEntity(entity.id);
	}
	/**
	 * method to search for a certain member by matching his name to that of the members
	 * 
	*@author omar fouda
	*
	*@param query, the string to be used for matching the members
	*@param entityID, id of the entity whose members we're searching
	*@param isAllowedToPost, boolean variable that indicates if the user is allowed to pos a topic, 
	*it is passed on when rendering
	*/
	public static void searchForMembers(String query, long entityID, boolean isAllowedToPost, boolean isSystemAdmin, boolean isOrganizationLead) {
		
		EEntity entity = EEntity.findById(entityID);
		List<User> members = new ArrayList<User>();

		List<User> members2 = new ArrayList<User>();

		for (int i = 0; i < entity.rolesAndUsers.size(); i++) {
			members2.add(entity.rolesAndUsers.get(i).user);
		}
		
		if (entity != null && members2 != null && members2.size() != 0) {
			for(User user: members2) {
				if (user.name.toLowerCase().indexOf(query.toLowerCase()) != -1) {
					members.add(user);
				}
			}
			
			if(query == "") {
				members = members2;
			}
			renderTemplate("Browse/viewEntityMembers.html",members,entity,isAllowedToPost,isSystemAdmin,isOrganizationLead);
			
		}
	}
	
	/**
	 * method to render the view of the organization's entities, it's used for the dynamic 
	 * view when editing an organization
	 * @author omar fouda
	 * @param orgId, id of the organization we want to go back to, it equals -1 if the method is called
	 * from a place where only the entity id is available
	 * @param entId, if of the entity that belongs to the org we want to go back to, it equals -1 if the method
	 * is called from a place where the organization id is available
	 */
	public static void back(long orgId, long entId){
		Organization org = null;
		if(orgId == -1){
			EEntity entity = EEntity.findById(entId);
			org = entity.organization;
		}
		else{
			org = Organization.findById(orgId);	
		}
		renderTemplate("Browse/viewEntitiesOfOrg.html",org);
	}
	
}
